package com.black.cat.jvm.classfile.constantpool;

import com.black.cat.jvm.classfile.ClassReader;
import com.black.cat.jvm.classfile.constantpool.impl.ConstantInfoNameAndType;
import com.black.cat.jvm.common.CommonValue;
import lombok.Data;

import java.util.Arrays;

/**
 * @Author blackcat
 * @create 2021/8/12 9:12
 * @version: 1.0
 * @description:常量池 通用格式
 * cp_info {
 * u1 tag;
 * u1 info[];
 * }
 */
@Data
public class ConstantPool {

    private final int constantPoolSize;

    private ConstantInfo[] constantInfos;


    public ConstantPool(ClassReader reader) {
        constantPoolSize = reader.nextU2ToInt();
        constantInfos = new ConstantInfo[constantPoolSize];
        for (int i = 1; i < constantPoolSize; i++) {

            int tag = reader.nextU1toInt();
            ConstantInfo constInfo = BaseConstantInfo.createConstantInfo(tag, reader, this);
            constantInfos[i] = constInfo;
            //所有的 8 字节的常量都占两个表成员（项）的空间。如果一个
            //CONSTANT_Long_info 或 CONSTANT_Double_info 结构的项在常量池中的索引为 n，则常量
            //池中下一个有效的项的索引为 n+2
            switch (tag) {
                case CommonValue.CONSTANT_POOL_TAG_LONG:
                case CommonValue.CONSTANT_POOL_TAG_DOUBLE:
                    i++;
                    break;
            }
        }
    }

    public String getUtfStringByIndex(int index) {
        return constantInfos[index].getValue();
    }


    public String getNameAndType(int idx) {
        ConstantInfoNameAndType constantInfo = (ConstantInfoNameAndType) this.constantInfos[idx];
        return constantInfo.getValue();
    }

    public int getSize() {
        return constantPoolSize;
    }

    @Override
    public String toString() {
        return "ConstantPool{" +
                "constantPoolSize=" + constantPoolSize +
                ", constantInfos=" + Arrays.toString(constantInfos) +
                '}';
    }
}
